﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Engine;

namespace GameOfCoins
{
	public partial class CWorldEditor : Form
	{
		private const int	m_iBorder		= 16;
		private CWorldCore	m_oWorldCore;
		private int			sel				= -1;
		private int			m_iElemCount	= -1;		//Used to relieve world core of to many calculations

		public CWorldEditor()
		{
			InitializeComponent();

			//Start engine
			m_oWorldCore = new CWorldCore();

			//Set elements
			setElements();
		}

//////////////////////////////////////////////////////////////////////////////////////////////////////
////////// UTILITIES

		//Init members and make controls visible (mandatory!)
		// - Load existing world
		//@ KR / 2014.06.25
		public void LoadWorld(string strWorldFile)
		{		
			//Make controls visible
			//TODO: Draw picturebox border after engine init (look better)
			pbPlayboard.Visible		= true;
			lvElements.Visible		= true;
			lblElemCount.Visible	= true;

			//Load world
			m_oWorldCore.LoadWorld(strWorldFile);

			//Resize control
			Rescale();

			//Set current elem count
			UpdateElemCount();

			//Set up animation core and show world
			CAnimationCore.SetGrid(true);
			CAnimationCore.s_pbPlayboard = pbPlayboard;
			CAnimationCore.StartPlayboardRenderer();
		}

		//Init members and make controls visible (mandatory!)
		// - Create new world
		//@ KR / 2014.07.07
		public void NewWorld(string strWorldFile)
		{		
			//Make controls visible
			//TODO: Draw picturebox border after engine init (look better)
			pbPlayboard.Visible		= true;
			lvElements.Visible		= true;
			lblElemCount.Visible	= true;

			//Load world
			m_oWorldCore.CreateWorld(strWorldFile);

			//Resize control
			Rescale();

			//Set up animation core and show world
			CAnimationCore.SetGrid(true);
			CAnimationCore.s_pbPlayboard = pbPlayboard;
			CAnimationCore.StartPlayboardRenderer();
		}

		//Set and realign elem counter
		//@ KR / 2014.07.08
		private void UpdateElemCount()
		{
			//Set animation counter
			m_iElemCount = m_oWorldCore.GetAnimatedCount();
			lblElemCount.Text = m_iElemCount.ToString() + " / 95";

			//Realign
			CUtilities.CenterLabel(lblElemCount);
		}

//////////////////////////////////////////////////////////////////////////////////////////////////////

		//Rescale form and all controls
		//@ EA / 2014.06.27
		private void Rescale()
		{
			//World dimensions
			int iWorldWidth = 0;
			int iWorldHeight = 0;

			//Resize control
			m_oWorldCore.GetWorldDimensions(ref iWorldWidth, ref iWorldHeight);
			pbPlayboard.Width = iWorldWidth;
			pbPlayboard.Height = iWorldHeight;
			CUtilities.CenterPictureBox(pbPlayboard);

			//Elem counter
			CUtilities.CenterLabel(lblElemCount);

			//Set brick selection position (X-Axis only!)
			lvElements.Location = new Point(pbPlayboard.Location.X + iWorldWidth + 20, pbPlayboard.Location.Y);
			lvElements.Height = iWorldHeight;
		}

		//Level Elemente der ListView anhängen
		//@ EA / 2014.06.27
		private void setElements()
		{
			//Show elements in ListView
			ImageList imageList = new ImageList();

			//Bilder der Elemente hinzufügen
			imageList.Images.Add(Engine.Properties.Resources.brick_stone);
			imageList.Images.Add(Engine.Properties.Resources.brick_stone_broken);
			imageList.Images.Add(Engine.Properties.Resources.spikes);
			imageList.Images.Add(Engine.Properties.Resources.coin);
			imageList.Images.Add(Engine.Properties.Resources.diamond);
			imageList.Images.Add(Engine.Properties.Resources.burger);
			imageList.Images.Add(Engine.Properties.Resources.teleport);

			//ImageList der ListView zuordnen
			lvElements.LargeImageList = imageList;

			//Elemente hinzufügen Stein
			ListViewItem lvItem = new ListViewItem();
			lvItem.ImageIndex = 0;
			lvItem.Text = "Stein";
			lvElements.Items.Add(lvItem);

			//Elemente hinzufügen Stein
			ListViewItem lvItemBroken = new ListViewItem();
			lvItemBroken.ImageIndex = 1;
			lvItemBroken.Text = "Stein (kaputt)";
			lvElements.Items.Add(lvItemBroken);

			//Elemente hinzufügen Spikes
			ListViewItem lvItemSpikes = new ListViewItem();
			lvItemSpikes.ImageIndex = 2;
			lvItemSpikes.Text = "Spikes";
			lvElements.Items.Add(lvItemSpikes);

			//Elemente hinzufügen Coin
			ListViewItem lvItemCoin = new ListViewItem();
			lvItemCoin.ImageIndex = 3;
			lvItemCoin.Text = "Münze";
			lvElements.Items.Add(lvItemCoin);

			//Elemente hinzufügen Diamond
			ListViewItem lvItemDiamond = new ListViewItem();
			lvItemDiamond.ImageIndex = 4;
			lvItemDiamond.Text = "Diamant";
			lvElements.Items.Add(lvItemDiamond);

			//Elemente hinzufügen Burger
			ListViewItem lvItemBurger = new ListViewItem();
			lvItemBurger.ImageIndex = 5;
			lvItemBurger.Text = "Burger";
			lvElements.Items.Add(lvItemBurger);

			//Elemente hinzufügen Teleport
			ListViewItem lvItemTeleport = new ListViewItem();
			lvItemTeleport.ImageIndex = 6;
			lvItemTeleport.Text = "Teleport";
			lvElements.Items.Add(lvItemTeleport);
		}

//////////////////////////////////////////////////////////////////////////////////////////////////////
////////// EVENTS

		//When first opened, show game setup
		// - Close game if setup gets cancled
		//@ KR / 2014.06.27
		private void CWorldEditor_Shown(object sender, EventArgs e)
		{
			WorldEditorSetup oSetup = new WorldEditorSetup(this);
			if(oSetup.ShowDialog() == DialogResult.Cancel)
				Close();
		}

		//Auswählen eines Elements der ListView
		//@ EA / 2014.06.27
		private void lvElements_SelectedIndexChanged(object sender, EventArgs e)
		{
			foreach (ListViewItem item in lvElements.SelectedItems)
			{
				sel = item.Index;
				sel++;

				//Change mouse cursor
				switch (sel) 
				{
					case 1:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.brick_stone.GetHicon());
						break;
					case 2:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.brick_stone_broken.GetHicon());
						break;
					case 3:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.spikes.GetHicon());
						break;
					case 4: 
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.coin.GetHicon());
						break;
					case 5:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.diamond.GetHicon());
						break;
					case 6:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.burger.GetHicon());
						break;
					case 7:
						pbPlayboard.Cursor = new Cursor(Engine.Properties.Resources.teleport.GetHicon());
						break;
					default :
						pbPlayboard.Cursor = Cursors.Default;
						break;
				}
				
			}
		}

//////////////////////////////////////////////////////////////////////////////////////////////////////
////////// CTRLS

		//Element setzen/entfernen mit Mausklick
		//@ EA / 2014.06.27
		private void pbPlayboard_MouseDown(object sender, MouseEventArgs e)
		{
			int iX = e.X / Const.GRID_DIM;
			int iY = e.Y / Const.GRID_DIM;

			if (e.Button == MouseButtons.Left)
			{
				if(m_iElemCount == 95)	//No more than 95 elements
					return;

				switch (sel) 
				{
					case 1:
						m_oWorldCore.SetBrick(Const.BLOCK_ROCK, iX, iY);
						break;
					case 2:
						m_oWorldCore.SetBrick(Const.BLOCK_ROCK, iX, iY);
						m_oWorldCore.DamagedBrick(iX, iY);
						break;
					case 3:
						m_oWorldCore.SetBrick(Const.BLOCK_SPIKES, iX, iY);
						break;
					case 4: 
						m_oWorldCore.SetUtil(Const.UTIL_COIN, iX, iY, true);
						break;
					case 5 :
						m_oWorldCore.SetUtil(Const.UTIL_DIAMOND, iX, iY, true, 10);
						break;
					case 6 :
						m_oWorldCore.SetUtil(Const.UTIL_STAMINA, iX, iY, true);
						break;
					case 7 :
						m_oWorldCore.SetUtil(Const.UTIL_TELEPORT, iX, iY, true);
						break;
				}
			}
			else
			{
				//Delete will always remove all
				m_oWorldCore.SetBrick(Const.BLOCK_ICE, iX, iY);
				m_oWorldCore.RemoveCoin(iX, iY);
				m_oWorldCore.RemovePowerUp(iX, iY);
			}

			
		}

		//Element setzen/entfernen per drag
		//@ KR / 2014.07.08
		private void pbPlayboard_MouseMove(object sender, MouseEventArgs e)
		{
			int iX = e.X / Const.GRID_DIM;
			int iY = e.Y / Const.GRID_DIM;

			//Within range?
			if(iX < 0 || iX >= Const.GRIDS_XAXIS || iY < 0 || iY >= Const.GRIDS_YAXIS)
				return;

			if (e.Button == MouseButtons.Left && sel > -1)
			{
				if(m_iElemCount == 95)	//No more than 95 elements
					return;

				CAnimationCore.StopPlayboardRenderer();

				switch (sel) 
				{
					case 1:
						m_oWorldCore.SetBrick(Const.BLOCK_ROCK, iX, iY);
						break;
					case 2:
						m_oWorldCore.SetBrick(Const.BLOCK_ROCK, iX, iY);
						m_oWorldCore.DamagedBrick(iX, iY);
						break;
					case 3: 
						m_oWorldCore.SetBrick(Const.BLOCK_SPIKES, iX, iY);
						break;
					case 4: 
						m_oWorldCore.SetUtil(Const.UTIL_COIN,iX, iY, true);
						break;
					case 5 :
						m_oWorldCore.SetUtil(Const.UTIL_DIAMOND, iX, iY, true, 10);
						break;
					case 6 :
						m_oWorldCore.SetUtil(Const.UTIL_STAMINA, iX, iY, true);
						break;
					case 7 :
						m_oWorldCore.SetUtil(Const.UTIL_TELEPORT, iX, iY, true);
						break;
				}

				CAnimationCore.StartPlayboardRenderer();
			}
			else if(e.Button == MouseButtons.Right)
			{
				CAnimationCore.StopPlayboardRenderer();

				//Delete will always remove all
				m_oWorldCore.SetBrick(Const.BLOCK_ICE, iX, iY);
				m_oWorldCore.RemoveCoin(iX, iY);
				m_oWorldCore.RemovePowerUp(iX, iY);

				CAnimationCore.StartPlayboardRenderer();
			}

			UpdateElemCount();
		}

		//Stop renderer and free world resources
		//@ KR / 2014.06.27
		private void btnBack_Click(object sender, EventArgs e)
		{
			CAnimationCore.StopPlayboardRenderer();
			CAnimationCore.Clear();

			m_oWorldCore.DeleteWorld();
		}

		private void btnSave_Click(object sender, EventArgs e)
		{
			if(m_oWorldCore.GetCoins() == 0)
			{
				MessageBox.Show("Sie müssen mindestens eine Münze plazieren", "Nicht möglich!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				return;
			}

			CAnimationCore.StopPlayboardRenderer();
			CAnimationCore.Clear();

			m_oWorldCore.SaveWorld();
			m_oWorldCore.DeleteWorld();

			Close();
		}
	}
}
